package br.brpv.silvestrin.conferencia.models.adapters;


import br.brpv.silvestrin.conferencia.R;
import br.brpv.silvestrin.conferencia.models.LoteOrigin;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Filter;

import java.util.*;

public class LoteOriginAdapter extends ArrayAdapter {

	 private Context mContext;
	    private int layoutResourceId;
	    private ArrayList<LoteOrigin> mObjects = null, mDisplayedObjects = null;

	    private Boolean mOutOfSync = false;
	    private boolean mNotifyOnChange = false;

	    private final Object mFilterLock = new Object();

	    private Filter filter = null;
	    private TextView viewToShowStockSum;

	    public LoteOriginAdapter(Context context, int layoutResourceId, ArrayList<LoteOrigin> data){
	        super(context, layoutResourceId, data);

	        this.mContext = context;
	        this.layoutResourceId = layoutResourceId;

	        mObjects = (data != null) ? data : new ArrayList<LoteOrigin>();
	        mDisplayedObjects = new ArrayList<LoteOrigin>(mObjects);

	        this.viewToShowStockSum = null;
	    }

	    public Context getContext() {
	        return mContext;
	    }

	    public ArrayList<LoteOrigin> getObjects() {
	        return mObjects;
	    }

	    protected Object getFilterLock() {
	        return mFilterLock;
	    }

	    protected boolean isOutOfSync() {
	        return mOutOfSync;
	    }

	    protected void setOutOfSync(boolean outOfSync) {
	        mOutOfSync = outOfSync;
	    }

	    public void setNotifyOnChange(boolean notifyOnChange) {
	        mNotifyOnChange = notifyOnChange;
	    }

	    public void add(LoteOrigin object) {
	        synchronized (mObjects) {
	            mObjects.add(object);
	        }

	        if (mNotifyOnChange) notifyDataSetChanged();
	    }
	    
	    public void addAll(LoteOrigin ... objects) {
	        synchronized (mObjects) {
	            for (LoteOrigin object : objects)
	                mObjects.add(object);
	        }

	        if (mNotifyOnChange) notifyDataSetChanged();
	    }

	    public void insert(LoteOrigin object, int index) {
	        synchronized (mObjects) {
	            mObjects.add(index, object);
	        }

	        if (mNotifyOnChange) notifyDataSetChanged();
	    }

	    public void remove(LoteOrigin object) {
	        synchronized (mObjects) {
	            mObjects.remove(object);
	        }

	        if (mNotifyOnChange) notifyDataSetChanged();
	    }

	    public void clear() {
	        synchronized (mObjects) {
	            mObjects = new ArrayList<LoteOrigin>();
	        }

	        if (mNotifyOnChange) notifyDataSetChanged();
	    }
	    
	    @Override
	    public void notifyDataSetChanged() {
	        boolean reapplyFilter;

	        synchronized (mFilterLock) {
	            reapplyFilter = mOutOfSync = (mLastFilter != null);
	        }

	        if (reapplyFilter) {
	            /* It would be amazing to only apply the filter to the
	             * new elements, but since the collection could have
	             * suffered unknown modifications, we can't.
	             */

	            getFilter().filter(mLastFilter);

	        } else {
	            synchronized (mObjects) {
	                mDisplayedObjects = new ArrayList<LoteOrigin>(mObjects);

	            }
	        }

	        doNotifyDataSetChanged();
	    }

	    protected void doNotifyDataSetChanged() {
	        super.notifyDataSetChanged();
	    }


	    public void setViewToShowStockSum(TextView viewToShowStockSum) {
	        this.viewToShowStockSum = viewToShowStockSum;
	    }

	    @Override
	    public int getCount() {
	        return mDisplayedObjects.size();
	    }

	    @Override
	    public LoteOrigin getItem(int position) {
	        return mDisplayedObjects.get(position);
	    }

	    @Override
	    public long getItemId(int position) {
	        return position;
	    }

	    @Override
	    public View getView(int position, View convertView, ViewGroup parent) {
	        View row = convertView;
	        LoteOriginHolder holder = null;

	        if(row == null)
	        {
	            LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
	            row = inflater.inflate(layoutResourceId, parent, false);

	            holder = new LoteOriginHolder();
	            holder.codLote = (TextView)row.findViewById(R.id.cod_lote_textView);
	            holder.almox = (TextView)row.findViewById(R.id.lote_list_almox_textView);
	            holder.codItem = (TextView)row.findViewById(R.id.lote_list_cod_item_textView);
	            holder.desc = (TextView)row.findViewById(R.id.lote_list_descr_textView);
	            holder.qtde = (TextView)row.findViewById(R.id.lote_list_qtde_textView);
	            holder.um = (TextView)row.findViewById(R.id.lote_list_um_textView);

	            row.setTag(holder);
	        }
	        else
	        {
	            holder = (LoteOriginHolder)row.getTag();
	        }

	        LoteOrigin loteOrigin = getItem(position);
	        if(loteOrigin != null){
	            if(holder.codLote != null) holder.codLote.setText(loteOrigin.getCod());
	            if(holder.almox != null) holder.almox.setText(loteOrigin.getAlmox());
	            if(holder.codItem != null) holder.codItem.setText(loteOrigin.getCodItem());
	            if(holder.desc != null) holder.desc.setText(loteOrigin.getDescr());
	            if(holder.qtde != null) holder.qtde.setText(loteOrigin.getQtde() + "");
	            if(holder.um != null) holder.um.setText(loteOrigin.getUm());
	        }
	        return row;
	    }

	    private static class LoteOriginHolder {
	        TextView codLote;
	        TextView almox;
	        TextView codItem;
	        TextView desc;
	        TextView qtde;
	        TextView um;
	    }

	    @Override
	    public Filter getFilter() {
	        if(filter == null)
	            filter = new LoteOriginFilter();
	        return filter;
	    }

	    private CharSequence mLastFilter = "";

	    private class LoteOriginFilter extends Filter {
	        @Override
	        protected FilterResults performFiltering(CharSequence constraintSeq) {
	            ArrayList<LoteOrigin> filteredObjects;

	            synchronized (mFilterLock) {
	                if (!mOutOfSync && mLastFilter != null && mLastFilter.equals(constraintSeq))
	                    return null;

	                mLastFilter = constraintSeq;
	            }

	            synchronized (mObjects) {
	                /* We'll make a copy of the list, so we can release the lock
	                 * as soon as possible.partial
	                 */
	                filteredObjects = new ArrayList<LoteOrigin>(mObjects);
	            }

	            if (constraintSeq == null || constraintSeq.length() == 0) /* Part of the Filter contract */
	                return resultsFromList(filteredObjects);

	            String constraint = constraintSeq.toString().toLowerCase();

	            ListIterator<LoteOrigin> it = filteredObjects.listIterator();

	            while (it.hasNext()) {
	            	LoteOrigin item = it.next();
	                StringTokenizer tokenizer = new StringTokenizer(constraint, " ");

	                String desc = item.getDescr().toLowerCase();
	                String cod = item.getCod().toLowerCase();

	                boolean match = true;

	                while(tokenizer.hasMoreTokens() && match) {
	                    String token = tokenizer.nextToken();

	                    if(!desc.contains(token) && !cod.contains(token)) {
	                        match = false;
	                    }
	                }

	                if (!match) it.remove();
	            }

	            return resultsFromList(filteredObjects);
	        }

	        @SuppressWarnings("unchecked")
			@Override
	        protected void publishResults(CharSequence constraint, FilterResults results) {
	            if (results != null) {
	                mDisplayedObjects = (ArrayList<LoteOrigin>) results.values;
	            }

	            doNotifyDataSetChanged();
	        }

	        protected FilterResults resultsFromList(ArrayList<LoteOrigin> list) {
	            FilterResults fr = new FilterResults();

	            fr.values = list;
	            fr.count = list.size();

	            return fr;
	        }
	    }

}
